#include "include/charRecognition.h"
#include <thread>
#include <iostream>
#include <string>

namespace char_recognition {
using namespace std;
using namespace cv;
const string charVocabulary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Vocabulary::Vocabulary()
:m_CurrentWordLength(0)
//  :m_hog(Size(SUBIMAGEWIDTH,SUBThreaIMAGEHEIGHT),Size(16,16),Size(8,8),Size(8,8),3)
{
#if 1
  Training();
	
//  test();
#else
  m_svm = cv::ml::SVM::create();
//  m_svm->setType(cv::ml::SVM::Types::C_SVC);
//  m_svm->setKernel(cv::ml::SVM::KernelTypes::LINEAR);
//  m_svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));
  m_svm->load("SVM_DATA.dat");
#endif
}

void Vocabulary::Training()
{
//  string Dir = "/res/images/charRecognition/";
 
	for(int i=0; i<8; i++)
	{
		std::vector<ImageData> data1;
		m_VocabularyDatas.push_back(data1);
	}
	
  for(int i=0; i<DATADIR.size(); i++)
  {
	  string Dir = "/system/media/res/other/CharRecognition/";
	  if(i < 26)
	  {
		  Dir += "BIG/";
	  }
	  else
	  {
		  Dir += "SMALL/";
	  }
	  
	  for(int j=0; j<8; j++)
	  {
		  char temp = '0'+j;
		  string filePath = Dir+DATADIR[i]+"/" + temp + ".png";
		  
		  cv::Mat srcImage = cv::imread(filePath, CV_LOAD_IMAGE_GRAYSCALE);
		  
		  if(srcImage.empty())
		  {
			  UDEBUG("FILE PATH:%s  is not exits.\n",filePath.data());
			  continue;
		  }
//	  cv::resize(srcImage,srcImage,Size(50,50));
		  cv::Mat binImage;
//		  cv::threshold(srcImage,binImage,0,255,THRESH_OTSU);
//		  binImage.copyTo(srcImage);
		  ImageData imageData1;
		  //原图像
		  imageData1.srcImage = srcImage;//srcImage
		  imageData1.ID = i;//ID
		
//		  getBlockDescriptoy(srcImage,imageData1.descriptor);
		  imageData1.elaborationImage = elaborationImage_1(srcImage);
		  getBlockDescriptoy(srcImage,imageData1.descriptor);
		  imageData1.lineCount = lineCount[i];
//		  UDEBUG("%s lineCount: %d\n",filePath.data(),imageData1.lineCount);
		  m_VocabularyDatas[j].push_back(imageData1);
	  }
  }
}
	double pixelDistance(double u, double v)
	{
		return std::sqrt(u*u + v*v);
	}
	double gaussianCoeff(double u, double v, double d0)
	{
		double d = pixelDistance(u, v);
#if 1
		return 1.0 - std::exp((-d*d) / (2*d0*d0));
#else
		double h=0;
		int n=4;
		if(d < 0)
		{
			h=0.0;
		}
		else
		{
			h = 1.0 / (1.0 + pow((d0 / d), 2 * n));
		}
		return h;
#endif
	}
	void Vocabulary::homoFilters(const Mat &srcImage, Mat &dst, double sigma)
	{
		if(srcImage.empty())
		{
			return ;
		}
		///log变换
		//将源图像转为float类型  然后进行log变换
		cv::Mat srcFloatImage;
		cv::Mat logImage;
		srcImage.convertTo(srcFloatImage,CV_32F);
		
		cv::log(srcFloatImage+1,logImage);
		
		///高通滤波
		//使滤波器的大小（M，N）为偶数来加速FFT计算
		Mat padded;
		int M = logImage.rows%2;
		int N = logImage.cols%2;
		copyMakeBorder(logImage, padded, 0, M, 0, N, BORDER_CONSTANT, Scalar::all(0));

		
		//傅里叶变换 FFT
		cv::Mat fourierImage;
//		UDEBUG("Hello World 1. % d %d %d %d\n",padded.rows, padded.cols,M,N);
		//如果图像row为81就挂了  opencv处的源码：if len > 1 && (len & 1) 就报
		cv::dct(padded,fourierImage);
//		UDEBUG("Hello World 2.\n");
		//构造一个高斯频域高通滤波器
//		double sigma = 2.5;
		cv::Point2f center;
		center.x = fourierImage.rows/2;
		center.y = fourierImage.cols/2;
		
		cv::Mat gaussFilter = cv::Mat::zeros(fourierImage.rows,fourierImage.cols, CV_32F);
		for(int row=0; row<fourierImage.rows; row++)
		{
			for(int col=0; col<fourierImage.cols; col++)
			{
				gaussFilter.at<float>(row,col) = gaussianCoeff(row, col, sigma);
			}
		}
		
		fourierImage = fourierImage.mul(gaussFilter);
		
		cv::Mat resultImage;
		cv::idct(fourierImage, resultImage, DFT_INVERSE);
		
		cv::exp(resultImage-1,resultImage);
		resultImage = resultImage * 255;
		resultImage.convertTo(dst,CV_8U);
	}
std::multimap<int,cv::Mat> Vocabulary::getTargetArea(const Mat &srcImage)
{
		multimap<int,cv::Mat> vResult;
		if(srcImage.rows < 10 || srcImage.cols < 10)
		{
			return vResult;
		}
		
		cv::Mat image_gay;
		if(srcImage.channels() != 1)
		{
			cv::cvtColor(srcImage, image_gay, CV_RGB2GRAY);
		}
		else
		{
			srcImage.convertTo(image_gay,CV_8U);
		}
#if 0
	
	cv::Mat Guass_image;
	image_gay.copyTo(Guass_image);
#if 0
	//分成5段进行二值化
	int offset1 = 80;
	int offset2 = 220;
	int offset3 = 430;
	int offset4 = 560;
	
	UDEBUG("Guass_image.rows = %d\n",Guass_image.rows);
	cv::Mat image1 = Guass_image.colRange(0,offset1);
	cv::Mat image2 = Guass_image.colRange(offset1,offset2);
	cv::Mat image3 = Guass_image.colRange(offset2,offset3);
	cv::Mat image4 = Guass_image.colRange(offset3,offset4);
	cv::Mat image5 = Guass_image.colRange(offset4,Guass_image.cols);
	
	homoFilters(image1,image1,1.2);
	homoFilters(image2,image2,1.2);
	homoFilters(image3,image3,1.4);
	homoFilters(image4,image4,1.2);
	homoFilters(image5,image5,1.2);
	
//	cv::GaussianBlur(image1,image1,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image2,image2,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image3,image3,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image4,image4,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image5,image5,cv::Size(3, 3), 0, 0);
	
//	cv::threshold(image1,image1,252,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image2,image2,252,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image3,image3,254,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image4,image4,252,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image5,image5,252,255,cv::THRESH_BINARY_INV);
	
	for(int row=0;row<Guass_image.rows; row++)
	{
		for(int col=0; col<Guass_image.cols; col++)
		{
			if(col < offset1)
			{
				Guass_image.at<uchar>(row,col) = image1.at<uchar>(row,col);
			}
			else if(col < offset2)
			{
				Guass_image.at<uchar>(row,col) = image2.at<uchar>(row,col-offset1);
			}
			else if(col < offset3)
			{
				Guass_image.at<uchar>(row,col) = image3.at<uchar>(row,col-offset2);
			}
			else if(col < offset4)
			{
				Guass_image.at<uchar>(row,col) = image4.at<uchar>(row,col-offset3);
			}
			else
			{
				Guass_image.at<uchar>(row,col) = image5.at<uchar>(row,col-offset4);
			}
		}
	}
#else
	int offset1 = 80;
	int offset2 = 220;
	int offset3 = 430;
	int offset4 = 560;
	
	UDEBUG("Guass_image.rows = %d\n",Guass_image.rows);
	cv::Mat image1 = Guass_image.colRange(0,offset1);
	cv::Mat image2 = Guass_image.colRange(offset1,offset2);
	cv::Mat image3 = Guass_image.colRange(offset2,offset3);
	cv::Mat image4 = Guass_image.colRange(offset3,offset4);
	cv::Mat image5 = Guass_image.colRange(offset4,Guass_image.cols);

//	charRecognitionVocabulary->homoFilters(image1,image1,1.0);
//	charRecognitionVocabulary->homoFilters(image2,image2,1.0);
//	charRecognitionVocabulary->homoFilters(image3,image3,1.0);
//	charRecognitionVocabulary->homoFilters(image4,image4,1.0);
//	charRecognitionVocabulary->homoFilters(image5,image5,1.0);

//	cv::GaussianBlur(image1,image1,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image2,image2,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image3,image3,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image4,image4,cv::Size(3, 3), 0, 0);
//	cv::GaussianBlur(image5,image5,cv::Size(3, 3), 0, 0);
	
	cv::threshold(image1,image1,252,255,cv::THRESH_TRIANGLE);
	cv::threshold(image2,image2,252,255,cv::THRESH_TRIANGLE);
	cv::threshold(image3,image3,254,255,cv::THRESH_TRIANGLE);
	cv::threshold(image4,image4,252,255,cv::THRESH_TRIANGLE);
	cv::threshold(image5,image5,252,255,cv::THRESH_TRIANGLE);
	
	for(int row=0;row<Guass_image.rows; row++)
	{
		for(int col=0; col<Guass_image.cols; col++)
		{
			if(col < offset1)
			{
				Guass_image.at<uchar>(row,col) = image1.at<uchar>(row,col);
			}
			else if(col < offset2)
			{
				Guass_image.at<uchar>(row,col) = image2.at<uchar>(row,col-offset1);
			}
			else if(col < offset3)
			{
				Guass_image.at<uchar>(row,col) = image3.at<uchar>(row,col-offset2);
			}
			else if(col < offset4)
			{
				Guass_image.at<uchar>(row,col) = image4.at<uchar>(row,col-offset3);
			}
			else
			{
				Guass_image.at<uchar>(row,col) = image5.at<uchar>(row,col-offset4);
			}
		}
	}
	
	cv::threshold(Guass_image,Guass_image,128,255,cv::THRESH_BINARY_INV);
#endif
	cv::Mat image_bin;
	Guass_image.copyTo(image_bin);
#else
	static int threshold = 100;
	cv::Mat image_bin;
	image_bin = toBinary(image_gay, threshold);
	threshold += 7;
	if(threshold > 121)
	{
		threshold = 100;
	}
#endif
	vResult = getAllConnectedDomain(image_bin);
		
	return vResult;
}
//char Vocabulary::search(Mat &srcImage)
//{
//
//  int srcCount = getLineDescriptor(srcImage);
//  std::vector<int> firstScreenResult;
//  for(int i=0; i<m_VocabularyData.size(); i++)
//  {
////    int tempIndex = firstScreenResult[i];
//    int tempCount = m_VocabularyData[i].lineCount;
////    cout << DATADIR[i] << "#srcImageCount:" << srcCount << "  distCount:" << tempCount << endl;
//    if(tempCount == srcCount)
//    {
//      firstScreenResult.push_back(i);
//    }
//  }
//
//  std::vector<cv::Mat> vTempImages;
//  cv::Mat elaImage = elaborationImage_1( srcImage );
//  for(int i=0; i<firstScreenResult.size(); i++)
//  {
//    int index = firstScreenResult[i];
//    vTempImages.push_back(getDifferenceImage(m_VocabularyData[index].srcImage,elaImage));
//  }
//  std::vector<int> secondScreenResult;
//  for(int i=0; i<firstScreenResult.size(); i++)
//  {
//    int tempIndex = firstScreenResult[i];
//    double distence = (double)cv::countNonZero(vTempImages[i])/cv::countNonZero(elaImage);
//
//    if(distence > 0.75)
//    {
//      secondScreenResult.push_back(tempIndex);
////      cout << DATADIR[tempIndex] << " : " << distence << endl;
//    }
//  }
//  int srcDescriptor[9] = {0,0,0,0,0,0,0,0,0};
//  getBlockDescriptoy(srcImage,srcDescriptor);
//  int minDistence = INT_MAX;
//  int bestMatchIndex = -1;
//  for(int i=0; i<secondScreenResult.size(); i++)
//  {
//    int tempIndex = secondScreenResult[i];
//    int *destDescriptor = m_VocabularyData[tempIndex].descriptor;
//    int sum = 0;
//    for(int k=0; k<9; k++)
//    {
//      sum += (destDescriptor[k]-srcDescriptor[k])*(destDescriptor[k]-srcDescriptor[k]);
//    }
////    cout << DATADIR[tempIndex] << " : " << sum << endl;
//    if(sum < minDistence)
//    {
//      minDistence = sum;
//      bestMatchIndex = tempIndex;
//    }
//  }
//  if(minDistence < 2500 && -1  != bestMatchIndex)
//  {
//    return DATADIR[bestMatchIndex];
//  }
//  else
//  {
//    return 0;
//  }
//}
std::vector<int>  Vocabulary::search(std::multimap<int,Mat> vSrcimages)
{
//	string result = "#";
	std::vector<int> result;
	for(int i=0; i<8; i++)
	{
		result.push_back(0);
	}
	
	std::multimap<int,int>  resultMap;
	std::multimap<int,Mat>::const_iterator it= vSrcimages.begin();
	for(; it != vSrcimages.end(); it++)
	{
		cv::Mat finalImage;
//		lineTransformImage(it->second,finalImage);
		finalImage = deleteEdge(it->second);
		if(finalImage.empty())
		{
			continue;
		}
//		cv::threshold(finalImage,finalImage,128,255,THRESH_BINARY_INV);
//		finalImage = getConnectedDomain(finalImage);
//		if((float)cv::countNonZero(finalImage)/(finalImage.rows*finalImage.cols) > 0.95)
//		{
//			continue;
//		}
		int index = it->first;
//		UDEBUG("index = %d \n",index);
		search(finalImage,index,resultMap);
		std::multimap<int,int>::const_iterator it2 = resultMap.begin();
		if(it2 == resultMap.end())
		{
		
		}
		else
		{
			int maxIndex = it2->second;
			result[it->first] = maxIndex+1;
		}
		resultMap.clear();
	}
	return result;
}
	
	
	int Vocabulary::getConnectedDomainCount(const Mat &srcImage)
	{
		if(srcImage.empty())
		{
			return 0;
		}
		cv::Mat tempImage;
		srcImage.copyTo(tempImage);
		
		cv::copyMakeBorder(tempImage,tempImage,5,5,5,5,BORDER_CONSTANT,Scalar(0,0,0));
		
		cv::Mat _lableImg;
		tempImage.copyTo(_lableImg);
		int label = 0;
		int rows = tempImage.rows-1;
		int cols = tempImage.cols-1;
		Mat mask(rows, cols, CV_8UC1);
		mask.setTo(0);
		
		for(int i=1; i < rows; i++)
		{
			uchar* data = _lableImg.ptr<uchar>(i);
			for(int j = 1; j < cols; j++)
			{
				if(data[j] == 0&&mask.at<uchar>(i,j)!=1)
				{
					mask.at<uchar>(i,j)=1;
					std::stack<std::pair<int,int>> neighborPixels;
					neighborPixels.push(std::pair<int,int>(i,j)); // pixel position: <i,j>
					++label; //begin with a new label
					while(!neighborPixels.empty())
					{
						//get the top pixel on the stack and label it with the same label
						std::pair<int,int> curPixel =neighborPixels.top();
						int curY = curPixel.first;
						int curX = curPixel.second;
						_lableImg.at<uchar>(curY, curX) = label;
						
						//pop the top pixel
						neighborPixels.pop();
						
						//push the 4-neighbors(foreground pixels)
#if 1
						if(curX-1 >= 0)
						{
							if(_lableImg.at<uchar>(curY,curX-1) == 0&&mask.at<uchar>(curY,curX-1)!=1) //leftpixel
							{
								neighborPixels.push(std::pair<int,int>(curY,curX-1));
								mask.at<uchar>(curY,curX-1)=1;
							}
							if(curY-1 >= 0)
							{
								if(_lableImg.at<uchar>(curY-1,curX-1) == 0&&mask.at<uchar>(curY-1,curX)!=1)
									// up pixel
								{
									neighborPixels.push(std::pair<int,int>(curY-1, curX));
									mask.at<uchar>(curY-1,curX)=1;
								}
							}
							if(curY+1 <= rows-1)
							{
								if(_lableImg.at<uchar>(curY+1,curX-1) == 0&&mask.at<uchar>(curY+1,curX)!=1)
									//down pixel
								{
									neighborPixels.push(std::pair<int,int>(curY+1,curX));
									mask.at<uchar>(curY+1,curX)=1;
								}
							}
						}
						if(curX+1 <=cols-1)
						{
							if(_lableImg.at<uchar>(curY,curX+1) == 0&&mask.at<uchar>(curY,curX+1)!=1)
								// right pixel
							{
								neighborPixels.push(std::pair<int,int>(curY,curX+1));
								mask.at<uchar>(curY,curX+1)=1;
							}
							if(curY-1 >= 0)
							{
								if(_lableImg.at<uchar>(curY-1,curX+1) == 0&&mask.at<uchar>(curY-1,curX)!=1)
									// up pixel
								{
									neighborPixels.push(std::pair<int,int>(curY-1, curX));
									mask.at<uchar>(curY-1,curX)=1;
								}
							}
							if(curY+1 <= rows-1)
							{
								if(_lableImg.at<uchar>(curY+1,curX+1) == 0&&mask.at<uchar>(curY+1,curX)!=1)
									//down pixel
								{
									neighborPixels.push(std::pair<int,int>(curY+1,curX));
									mask.at<uchar>(curY+1,curX)=1;
								}
							}
						}
						if(curY-1 >= 0)
						{
							if(_lableImg.at<uchar>(curY-1,curX) == 0&&mask.at<uchar>(curY-1,curX)!=1)
								// up pixel
							{
								neighborPixels.push(std::pair<int,int>(curY-1, curX));
								mask.at<uchar>(curY-1,curX)=1;
							}
						}
						if(curY+1 <= rows-1)
						{
							if(_lableImg.at<uchar>(curY+1,curX) == 0&&mask.at<uchar>(curY+1,curX)!=1)
								//down pixel
							{
								neighborPixels.push(std::pair<int,int>(curY+1,curX));
								mask.at<uchar>(curY+1,curX)=1;
							}
						}
#else
#endif
					}
				}
			}
		}
//  cout << "ConnectedDomainCount: " << label << endl;
		return label;
	}
	
	std::vector< cv::Point2i> getLeftPoints(const cv::Mat &srcImage)
	{
		std::vector< cv::Point2i > leftPoints;
		for(int row=0; row<srcImage.rows;row ++)
		{
			bool left = true;
			for(int col=0; col<srcImage.cols; col++)
			{
				if(srcImage.at<uchar>(row,col) > 0 && left)
				{
					leftPoints.push_back(cv::Point2i(row,col));
					left = false;
				}
			}
		}
		return leftPoints;
	}
	std::vector< cv::Point2i> getRightPoints(const cv::Mat &srcImage)
	{
		std::vector< cv::Point2i > rightPoints;
		for(int row=0; row<srcImage.rows;row ++)
		{
			bool right = true;
			for(int col=0; col<srcImage.cols; col++)
			{
				if(srcImage.at<uchar>(row,srcImage.cols-col-1) > 0 && right)
				{
					rightPoints.push_back(cv::Point2i(row,srcImage.cols-col-1));
					right = false;
				}
			}
		}
		return rightPoints;
	}
	
	double getSlopeVariance(std::vector< cv::Point2i > &pints)
	{
		std::vector<double> Slope;
		for(int i=4; i<pints.size()-6; i++)
		{
			cv::Point2i p1 = pints[i];
			cv::Point2i p2 = pints[i+3];
			double slope = (double)(p1.y-p2.y)/(p1.x-p2.x);
			Slope.push_back(slope);
		}
		
		double Avg = 0;
		for(int i=0; i<Slope.size(); i++)
		{
			Avg += Slope[i]/Slope.size();
		}
		
		double Variance = 0;
		for(int i=0; i<Slope.size(); i++)
		{
			Variance += (Slope[i]-Avg)*(Slope[i]-Avg);
		}
		Variance /= Slope.size();
		return Variance;
	}
	
void Vocabulary::search(Mat &srcImage, const int &index, std::multimap<int, int> &resultMap)
{
	if(srcImage.rows < 0 || srcImage.cols < 0)
	{
		return ;
	}
	int srcCount2 = getConnectedDomainCount(srcImage);
	cv::Mat elaborationImage = elaborationImage_1(srcImage);
	cv::resize(srcImage,srcImage,cv::Size(destImageWidth,destImageHeight));
	
	std::vector<int> firstScreenResult;
	for(int i=0; i<m_VocabularyDatas[index].size(); i++)
	{
		
		int tempCount = m_VocabularyDatas[index][i].lineCount;
//		UDEBUG("%c : currentImage = %d   srcImage = %d \n",DATADIR[m_VocabularyDatas[index][i].ID],srcCount2,tempCount);
		//第一个和最后两个形变太严重  取消闭环检测这一步
//		if(srcCount2 == tempCount)
//		if((0 == index && 27== i) || (1 == i && 7 == index))
//		{
//			firstScreenResult.push_back(i);
//		}else
		if(srcCount2 == tempCount || 0 == index || 7 == index)
		{
			firstScreenResult.push_back(i);
		}
	}
	std::vector<int> secondScreenResult;
	std::vector<double> secondDistenceResult;
	for(int i=0; i<firstScreenResult.size(); i++)
	{
		int index1 = firstScreenResult[i];
		cv::Mat elaborationTemp = getDifferenceImage(m_VocabularyDatas[index][index1].srcImage,srcImage);
//		UDEBUG("countNonZero:src %d   dest %d \n",cv::countNonZero(srcImage),cv::countNonZero(m_VocabularyData[index].srcImage));
		double distence = (double)cv::countNonZero(elaborationTemp)/(double)cv::countNonZero(srcImage);
//		double distence2 = (double)cv::countNonZero(elaborationTemp)/(double)cv::countNonZero(m_VocabularyDatas[index][index1].srcImage);
//		UDEBUG("%c : distence = %f   distence2 = %f\n",DATADIR[m_VocabularyDatas[index][index1].ID],distence,distence2);
//		UDEBUG("%c : distence = %f\n",DATADIR[m_VocabularyDatas[index][index1].ID],distence);
//		if(distence > 0.6 || distence2 > 0.6)
		if(distence > 0.4)
		{
			secondScreenResult.push_back(index1);
//			secondDistenceResult.push_back(distence>distence2?(1.1-distence):(1.1-distence2));
			secondDistenceResult.push_back(1.1-distence);
		}
	}
	int srcDescriptor[9] = {0,0,0,0,0,0,0,0,0};
	
	getBlockDescriptoy(srcImage,srcDescriptor);
	int minDistence = INT_MAX;
	double currentDistence = 1.0;
	int bestMatchIndex = -1;
	for(int i=0; i<secondScreenResult.size(); i++)
	{
		int tempIndex = secondScreenResult[i];
		int *destDescriptor = m_VocabularyDatas[index][tempIndex].descriptor;
		long sum = 0;
		{
			for(int k=0; k<9; k++)
			{
				sum += (destDescriptor[k]-srcDescriptor[k])*(destDescriptor[k]-srcDescriptor[k]);
			}
		}
//		UDEBUG("%c @ %f  min:%f \n",DATADIR[m_VocabularyDatas[index][tempIndex].ID],(double)sum*secondDistenceResult[i],(double)minDistence * currentDistence);
		if(((double)sum*secondDistenceResult[i]) < ((double)minDistence * currentDistence))
		{
			minDistence = sum;
			currentDistence = secondDistenceResult[i];
			bestMatchIndex = tempIndex;
			
		}
	}
	if(minDistence* currentDistence < 1500)
	{
		int resultID = m_VocabularyDatas[index][bestMatchIndex].ID;
		//如果是'D' 'O' 'Q'  或者反放的'D' 'Q'
		if(3==resultID || 14==resultID || 16==resultID || 29==resultID || 37==resultID)
		{
			if(minDistence* currentDistence < 100) //如果相似距离小于100 则认为正确
			{
				// do nothing
			}
			else//否则进行一些判断
			{
				std::vector< cv::Point2i > leftPoints = getLeftPoints(srcImage);
				std::vector< cv::Point2i > rightPoints = getRightPoints(srcImage);
				if(getSlopeVariance(leftPoints) < 0.05) //如果左面有一条直线  是D
				{
					resultID = 3;
				}
				else if(getSlopeVariance(rightPoints) < 0.05)//如果右面有一条直线  是反D
				{
					resultID = 29;
				}
				else //判断QO 和反Q
				{
#if 0

#endif
				}
			}
		}
		
		//UDEBUG("result:%c.\n",DATADIR[resultID]);
		resultMap.insert(std::make_pair(minDistence,resultID));
		
	}
	return ;
}

int getIndexFromCol(int cols,int ImageCols)
{
	int arr[] = {30,75,145,230,300,400,510,570};
//	int temp = ImageCols/16;
	if(cols < arr[1])
	{
		return 0;
	}
	else if(cols < arr[2])
	{
		return 1;
	}
	else if(cols < arr[3])
	{
		return 2;
	}
	else if(cols < arr[4])
	{
		return 3;
	}
	else if(cols < arr[5])
	{
		return 4;
	}
	else if(cols < arr[6])
	{
		return 5;
	}
	else if(cols < arr[7])
	{
		return 6;
	}
	else
	{
		return 7;
	}
}
std::multimap<int,Mat> Vocabulary::getAllConnectedDomain(const Mat &srcImage)
{
//	std::vector< cv::Mat> v_result;
	std::multimap<int,Mat> v_result;
	if(srcImage.empty())
	{
		return v_result;
	}
	
	cv::Mat _lableImg;
	_lableImg = srcImage.clone();
	int label = 0;
	int rows = srcImage.rows;
	int cols = srcImage.cols;
	cv::Mat mask = cv::Mat::zeros(rows, cols, CV_8U);
	int VALUE = 0;
	for(int j = 0; j < cols; j++)
	{
		for(int i=0; i < rows; i++)
		{
			if(_lableImg.at<uchar>(i,j) == VALUE && mask.at<uchar>(i,j)!=1)
			{
				mask.at<uchar>(i,j)=1;
				std::stack<std::pair<int,int>> neighborPixels;
				neighborPixels.push(std::pair<int,int>(i,j)); // pixel position: <i,j>
				++label;
				while(!neighborPixels.empty())
				{
					//get the top pixel on the stack and label it with the same label
					std::pair<int,int> curPixel =neighborPixels.top();
					int curY = curPixel.first;
					int curX = curPixel.second;
					_lableImg.at<uchar>(curY, curX) = label;
					
					//pop the top pixel
					neighborPixels.pop();
					
					//push the 4-neighbors(foreground pixels)
					
					if(curX-1 >= 0)
					{
						if(_lableImg.at<uchar>(curY,curX-1) == VALUE&&mask.at<uchar>(curY,curX-1)!=1) //leftpixel
						{
							neighborPixels.push(std::pair<int,int>(curY,curX-1));
							mask.at<uchar>(curY,curX-1)=1;
						}
						if(curY-1 >= 0)
						{
							if(_lableImg.at<uchar>(curY-1,curX-1) == VALUE&&mask.at<uchar>(curY-1,curX)!=1)
								// up pixel
							{
								neighborPixels.push(std::pair<int,int>(curY-1, curX));
								mask.at<uchar>(curY-1,curX)=1;
							}
						}
						if(curY+1 <= rows-1)
						{
							if(_lableImg.at<uchar>(curY+1,curX-1) == VALUE&&mask.at<uchar>(curY+1,curX)!=1)
								//down pixel
							{
								neighborPixels.push(std::pair<int,int>(curY+1,curX));
								mask.at<uchar>(curY+1,curX)=1;
							}
						}
					}
					if(curX+1 <=cols-1)
					{
						if(_lableImg.at<uchar>(curY,curX+1) == VALUE&&mask.at<uchar>(curY,curX+1)!=1)
							// right pixel
						{
							neighborPixels.push(std::pair<int,int>(curY,curX+1));
							mask.at<uchar>(curY,curX+1)=1;
						}
						if(curY-1 >= 0)
						{
							if(_lableImg.at<uchar>(curY-1,curX+1) == VALUE&&mask.at<uchar>(curY-1,curX)!=1)
								// up pixel
							{
								neighborPixels.push(std::pair<int,int>(curY-1, curX));
								mask.at<uchar>(curY-1,curX)=1;
							}
						}
						if(curY+1 <= rows-1)
						{
							if(_lableImg.at<uchar>(curY+1,curX+1) == VALUE&&mask.at<uchar>(curY+1,curX)!=1)
								//down pixel
							{
								neighborPixels.push(std::pair<int,int>(curY+1,curX));
								mask.at<uchar>(curY+1,curX)=1;
							}
						}
					}
					if(curY-1 >= 0)
					{
						if(_lableImg.at<uchar>(curY-1,curX) == VALUE&&mask.at<uchar>(curY-1,curX)!=1)
							// up pixel
						{
							neighborPixels.push(std::pair<int,int>(curY-1, curX));
							mask.at<uchar>(curY-1,curX)=1;
						}
					}
					if(curY+1 <= rows-1)
					{
						if(_lableImg.at<uchar>(curY+1,curX) == VALUE&&mask.at<uchar>(curY+1,curX)!=1)
							//down pixel
						{
							neighborPixels.push(std::pair<int,int>(curY+1,curX));
							mask.at<uchar>(curY+1,curX)=1;
						}
					}
				}
			}
		}
	}
	
	std::vector< std::vector<cv::Point2i> > vv_points;
	
	for(int k=0; k<=label; k++)
	{
		std::vector<cv::Point2i> temp;
		vv_points.push_back(temp);
	}
	
	for(int j=0; j<cols; j++)
	{
		for(int i=0; i<rows; i++)
		{
			uchar labelValue = _lableImg.at<uchar>(i,j);
			if(labelValue < vv_points.size())
			{
				vv_points[labelValue].push_back(cv::Point2i(i,j));
			}
		}
	}
	//draw
	for(int k=1; k<vv_points.size(); k++) {
		std::vector<cv::Point2i> temp = vv_points[k];
		if (temp.size() < 200 || temp.size() > 10000) {
			continue;
		}
		cv::Mat destImage = cv::Mat::zeros(srcImage.rows, srcImage.cols, CV_8U);
		for (int t = 0; t < temp.size(); t++) {
			cv::Point2i point = temp[t];
			destImage.at<uchar>(point.x, point.y) = 255;
		}
		int minColPos = srcImage.cols;
		int maxColPos = 0;
		bool Dataflg = false;
		int topRow = 0;
		int bottomRow = 100;

#if 1
		int *rowData = new int[destImage.rows];
		memset(rowData, 0, destImage.rows * sizeof(int));
		int *colData = new int[destImage.cols];
		memset(colData, 0, destImage.cols * sizeof(int));
		
		for (int col = 0; col < destImage.cols; col++) {
			int count = 0;
			for (int row = 0; row < destImage.rows; row++) {
				uchar value = destImage.at<uchar>(row, col);
				if (value > 0) {
					rowData[row]++;
					colData[col]++;
				}
			}
		}
		
		for (int index = 0; index < destImage.rows; index++) {
			
			if (rowData[index] > 2 && !Dataflg) {
				topRow = index;
				Dataflg = true;
			} else if (rowData[index] < 2 && Dataflg) {
				bottomRow = index;
				Dataflg = false;
			}
		}
		Dataflg = false;
		for (int index = 0; index < destImage.cols; index++) {
			if (colData[index] > 2 && !Dataflg) {
				minColPos = index;
				Dataflg = true;
			} else if (colData[index] < 2 && Dataflg) {
				maxColPos = index;
				Dataflg = false;
			}
			
		}
//		UDEBUG("topRow : %d   bottomRow:%d \n",topRow,bottomRow);
		delete[]rowData;
		delete[]colData;
#else
		for (int row = 0; row < destImage.rows; row++) {
			if (cv::countNonZero(destImage.rowRange(row, row + 1)) > 2) {
				int left = -1;
				int right = -1;
				for (int col = 0; col < destImage.cols; col++) {
					if (destImage.at<uchar>(row, col) > 0 && left == -1) {
						left = col;
						if(left < minColPos)
						{
							minColPos = left;
						}
						if(left > maxColPos)
						{
							maxColPos = left;
						}
					}
					if (destImage.at<uchar>(row, destImage.cols - col - 1) > 0 && right == -1) {
						right = destImage.cols - col - 1;
					}
				}
			}
			
		}
#endif
	
		cv::Mat resultImage;
		resultImage = deleteEdge(destImage);
//		destImage.copyTo(resultImage);
//		if (!(topRow <20 || topRow > 80 || bottomRow < 70) &&
		if (!(topRow > 80 || bottomRow < 70) &&
//				resultImage.rows > 40 && resultImage.cols > 30 &&
				(double) resultImage.rows / resultImage.cols < 3.0 &&
		    (double) resultImage.rows / resultImage.cols > 0.3) {
				
				v_result.insert(std::make_pair(getIndexFromCol((minColPos+maxColPos)/2,srcImage.cols),resultImage));
		}
	}
	return v_result;
}
Mat Vocabulary::getConnectedDomain(const Mat &srcImage)
{
    if(srcImage.empty())
    {
      return srcImage;
    }
    cv::Mat _lableImg;
    _lableImg = srcImage.clone();
    int label = 0;
    int rows = srcImage.rows;
    int cols = srcImage.cols;
//  cout << "hello World. 1.03" << rows << cols<< endl;
    cv::Mat mask = cv::Mat::zeros(rows, cols, CV_8U);
//  cout << "hello World. 1.1" << endl;
    for(int i=0; i < rows; i++)
    {
      for(int j = 0; j < cols; j++)
      {
        if(_lableImg.at<uchar>(i,j) == 255 && mask.at<uchar>(i,j)!=1)
        {
          mask.at<uchar>(i,j)=1;
          std::stack<std::pair<int,int>> neighborPixels;
          neighborPixels.push(std::pair<int,int>(i,j)); // pixel position: <i,j>
          ++label; //begin with a new label
//              cout << label << endl;
          while(!neighborPixels.empty())
          {
            //get the top pixel on the stack and label it with the same label
            std::pair<int,int> curPixel =neighborPixels.top();
            int curY = curPixel.first;
            int curX = curPixel.second;
            _lableImg.at<uchar>(curY, curX) = label;
            
            //pop the top pixel
            neighborPixels.pop();
            
            //push the 4-neighbors(foreground pixels)
            
            if(curX-1 >= 0)
            {
              if(_lableImg.at<uchar>(curY,curX-1) == 255&&mask.at<uchar>(curY,curX-1)!=1) //leftpixel
              {
                neighborPixels.push(std::pair<int,int>(curY,curX-1));
                mask.at<uchar>(curY,curX-1)=1;
              }
              if(curY-1 >= 0)
              {
                if(_lableImg.at<uchar>(curY-1,curX-1) == 255&&mask.at<uchar>(curY-1,curX)!=1)
                  // up pixel
                {
                  neighborPixels.push(std::pair<int,int>(curY-1, curX));
                  mask.at<uchar>(curY-1,curX)=1;
                }
              }
              if(curY+1 <= rows-1)
              {
                if(_lableImg.at<uchar>(curY+1,curX-1) == 255&&mask.at<uchar>(curY+1,curX)!=1)
                  //down pixel
                {
                  neighborPixels.push(std::pair<int,int>(curY+1,curX));
                  mask.at<uchar>(curY+1,curX)=1;
                }
              }
            }
            if(curX+1 <=cols-1)
            {
              if(_lableImg.at<uchar>(curY,curX+1) == 255&&mask.at<uchar>(curY,curX+1)!=1)
                // right pixel
              {
                neighborPixels.push(std::pair<int,int>(curY,curX+1));
                mask.at<uchar>(curY,curX+1)=1;
              }
              if(curY-1 >= 0)
              {
                if(_lableImg.at<uchar>(curY-1,curX+1) == 255&&mask.at<uchar>(curY-1,curX)!=1)
                  // up pixel
                {
                  neighborPixels.push(std::pair<int,int>(curY-1, curX));
                  mask.at<uchar>(curY-1,curX)=1;
                }
              }
              if(curY+1 <= rows-1)
              {
                if(_lableImg.at<uchar>(curY+1,curX+1) == 255&&mask.at<uchar>(curY+1,curX)!=1)
                  //down pixel
                {
                  neighborPixels.push(std::pair<int,int>(curY+1,curX));
                  mask.at<uchar>(curY+1,curX)=1;
                }
              }
            }
            if(curY-1 >= 0)
            {
              if(_lableImg.at<uchar>(curY-1,curX) == 255&&mask.at<uchar>(curY-1,curX)!=1)
                // up pixel
              {
                neighborPixels.push(std::pair<int,int>(curY-1, curX));
                mask.at<uchar>(curY-1,curX)=1;
              }
            }
            if(curY+1 <= rows-1)
            {
              if(_lableImg.at<uchar>(curY+1,curX) == 255&&mask.at<uchar>(curY+1,curX)!=1)
                //down pixel
              {
                neighborPixels.push(std::pair<int,int>(curY+1,curX));
                mask.at<uchar>(curY+1,curX)=1;
              }
            }
          }
        }
      }
    }
    cv::Mat maxAreaDomain;
    int maxPixCount = 0;
    for(int k=1; k<=label; k++)
    {
      Mat tempImage = cv::Mat::zeros(rows, cols, CV_8U);
      for(int i=0;i<rows; i++)
      {
        for(int j=0;j<cols;j++)
        {
          if(k == _lableImg.at<uchar>(i,j))
          {
            tempImage.at<uchar>(i,j)= 255;
          }
        }
      }
      if(maxPixCount < cv::countNonZero(tempImage))
      {
        maxAreaDomain = tempImage.clone();
        maxPixCount = cv::countNonZero(tempImage);
      }
      else
      {
        tempImage.release();
      }
    }
    return maxAreaDomain.clone();
}
Mat Vocabulary::elaborationImage_1(const Mat &srcImage)
{
	//最好在图像边上留一点空的边框  不然容易出问题
	if(srcImage.type()!=CV_8UC1)
	{
		printf("只能处理二值或灰度图像\n");
		return cv::Mat();
	}
	cv::Mat dst;
	//非原地操作时候，copy src到dst
	if(dst.data!=srcImage.data)
	{
		srcImage.copyTo(dst);
	}
	cv::copyMakeBorder(dst,dst,2,2,2,2,BORDER_CONSTANT,Scalar(0,0,0));
#if 0
	cv::Mat skel(dst.size(), CV_8UC1, cv::Scalar(0));
    cv::Mat temp(dst.size(), CV_8UC1);

    cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
    bool done;
    int count = 0;
    do
    {
        cv::morphologyEx(dst, temp, cv::MORPH_OPEN, element);
        cv::bitwise_not(temp, temp);
        cv::bitwise_and(dst, temp, temp);
        cv::bitwise_or(skel, temp, skel);
        cv::erode(dst, dst, element);

        double max;
        cv::minMaxLoc(dst, 0, &max);
        done = (max == 0);
        count ++;
      } while (!done && count<100);

        dst = skel;
#else
	int i, j, n;
	int width, height;
	//之所以减1，是方便处理8邻域，防止越界
	width = dst.cols -1;
	height = dst.rows -1;
	int step = dst.step;
	int  p2,p3,p4,p5,p6,p7,p8,p9;
	uchar* img;
	bool ifEnd;
	cv::Mat tmpimg;
	int dir[4] = {-step, step, 1, -1};
	
	while(1)
	{
		//分四个子迭代过程，分别对应北，南，东，西四个边界点的情况
		ifEnd = false;
		for(n =0; n < 4; n++)
		{
			dst.copyTo(tmpimg);
			img = tmpimg.data;
			for(i = 1; i < height; i++)
			{
				img += step;
				for(j =1; j<width; j++)
				{
					uchar* p = img + j;
					//如果p点是背景点或者且为方向边界点，依次为北南东西，继续循环
					if(p[0]==0||p[dir[n]]>0) continue;
					p2 = p[-step]>0?1:0;
					p3 = p[-step+1]>0?1:0;
					p4 = p[1]>0?1:0;
					p5 = p[step+1]>0?1:0;
					p6 = p[step]>0?1:0;
					p7 = p[step-1]>0?1:0;
					p8 = p[-1]>0?1:0;
					p9 = p[-step-1]>0?1:0;
					//8 simple判定
					int is8simple = 1;
					if(p2==0&&p6==0)
					{
						if((p9==1||p8==1||p7==1)&&(p3==1||p4==1||p5==1))
							is8simple = 0;
					}
					if(p4==0&&p8==0)
					{
						if((p9==1||p2==1||p3==1)&&(p5==1||p6==1||p7==1))
							is8simple = 0;
					}
					if(p8==0&&p2==0)
					{
						if(p9==1&&(p3==1||p4==1||p5==1||p6==1||p7==1))
							is8simple = 0;
					}
					if(p4==0&&p2==0)
					{
						if(p3==1&&(p5==1||p6==1||p7==1||p8==1||p9==1))
							is8simple = 0;
					}
					if(p8==0&&p6==0)
					{
						if(p7==1&&(p3==9||p2==1||p3==1||p4==1||p5==1))
							is8simple = 0;
					}
					if(p4==0&&p6==0)
					{
						if(p5==1&&(p7==1||p8==1||p9==1||p2==1||p3==1))
							is8simple = 0;
					}
					int adjsum;
					adjsum = p2 + p3 + p4+ p5 + p6 + p7 + p8 + p9;
					//判断是否是邻接点或孤立点,0,1分别对于那个孤立点和端点
					if(adjsum!=1&&adjsum!=0&&is8simple==1)
					{
						dst.at<uchar>(i,j) = 0; //满足删除条件，设置当前像素为0
						ifEnd = true;
					}
					
				}
			}
		}
		//已经没有可以细化的像素了，则退出迭代
		if(!ifEnd) break;
	}
#endif
	return dst;
}

void Vocabulary:: lineTransformImage(const Mat &srcImage, Mat &destImage)
{
		if(srcImage.rows < 0 || srcImage.cols < 0)
		{
			return ;
		}
		destImage = cv::Mat::zeros(srcImage.rows,srcImage.cols*2,CV_8U);
		
		//获取图片的斜率
//  方法：遍历图片左边的所有点的斜率，找出斜率点数最多的一个作为该图片的斜率
//  对图像的每个像素点使用该斜率进行矫正
		//get slope
		vector<Point2f> imageLeftXPoints;
		for(int row=0; row<srcImage.rows; row++)
		{
			for(int col=0; col<srcImage.cols; col++)
			{
				if(srcImage.at<uchar>(row,col) != 0)
				{
					imageLeftXPoints.push_back(Point2f(row,col));
					break;
				}
			}
		}
		cv::Vec4f lines;
		cv::fitLine(imageLeftXPoints,lines,CV_DIST_HUBER,0,0.01,0.01);
		
		
		double k = lines[1] / lines[0];
		double b = lines[3]-(lines[2]*k);
//		UDEBUG("k = %f  b= %f \n",k,b);
		for(int row=0; row<srcImage.rows; row++)
		{
			int offset = floatToInt(((float)row*k+b));
			for(int col=0;col<srcImage.cols; col++)
			{
				if(255 == srcImage.at<uchar>(row,col))
				{
					destImage.at<uchar>(row,(col-offset+srcImage.cols)) = 255;
				}
			}
		}
		destImage = deleteEdge(destImage);
		return ;
		
}
Mat Vocabulary::deleteNoise(const Mat &srcImage)
{
  if(srcImage.rows < 0 || srcImage.cols < 0)
  {
    return cv::Mat();
  }
  //去噪声
  unsigned char *imageArrresult = new unsigned char[srcImage.rows * srcImage.cols];
  memset(imageArrresult,0,srcImage.rows * srcImage.cols);
  for(int row=1;row<srcImage.rows-1; row++)
  {
    for(int col=1; col<srcImage.cols-1; col++)
    {
      int avg = srcImage.at<unsigned char>((row-1)*srcImage.cols + (col-1)) + srcImage.at<unsigned char>((row-1)*srcImage.cols + (col+0))
               +srcImage.at<unsigned char>((row-1)*srcImage.cols + (col+1)) + srcImage.at<unsigned char>((row+0)*srcImage.cols + (col-1))
               +srcImage.at<unsigned char>((row+0)*srcImage.cols + (col+1)) + srcImage.at<unsigned char>((row+1)*srcImage.cols + (col-1))
               +srcImage.at<unsigned char>((row+1)*srcImage.cols + (col+0)) + srcImage.at<unsigned char>((row+1)*srcImage.cols + (col+1));
       avg /= 8;

       if(avg > 128)
       {
         imageArrresult[(row+0)*srcImage.cols + (col+0)] = 255;
       }
       else
       {
          imageArrresult[(row+0)*srcImage.cols + (col+0)] = 0;
       }
    }
  }
	cv::Mat result = cv::Mat(srcImage.rows,srcImage.cols,srcImage.type(),imageArrresult).clone();
	delete imageArrresult;
  return result;
}

Mat Vocabulary::deleteEdge(const Mat &srcImage)
{
#if 1
	if(srcImage.empty())
	{
		return srcImage;
	}
	
	int *rowData = new int[srcImage.rows];
	memset(rowData,0,srcImage.rows* sizeof(int));
	int *colData = new int[srcImage.cols];
	memset(colData,0,srcImage.cols* sizeof(int));
	
	for (int col = 0; col < srcImage.cols; col++)
	{
		int count = 0;
		for(int row=0; row<srcImage.rows; row++)
		{
			uchar value = srcImage.at<uchar>(row,col);
			if(value > 0)
			{
				rowData[row] ++;
				colData[col] ++;
			}
		}
	}
	
	cv::Mat destImage;
	destImage  = srcImage.clone();
	
	int bestTopRow = 0;//列的上边界
	int bestRowCount = 0;
	bool isDataFlg = false;
	int Row = 0;
	int rowCount = 0;
	for(int i=0; i<srcImage.rows; i++)
	{
		if(rowData[i])
		{
			if(isDataFlg)
			{
				rowCount ++;
			}
			else
			{
				Row = i;
				rowCount = 1;
				isDataFlg = true;
			}
		}
		else
		{
			isDataFlg = false;
		}
		
		if(rowCount > bestRowCount)
		{
			bestTopRow = Row;
			bestRowCount = rowCount;
		}
	}
	if(bestRowCount > 10)
	{
		destImage = destImage.rowRange(bestTopRow,bestTopRow+bestRowCount).clone();
	}
	
	int bestCol = 0;//列的上边界
	int bestColCount = 0;
	int Col = 0;
	int colCount = 0;
	isDataFlg = false;
	for(int i=0; i<srcImage.cols; i++)
	{
		if(colData[i])
		{
			if(isDataFlg)
			{
				colCount ++;
			}
			else
			{
				Col = i;
				colCount = 1;
				isDataFlg = true;
			}
		}
		else
		{
			isDataFlg = false;
		}
		
		if(colCount > bestColCount)
		{
			bestCol = Col;
			bestColCount = colCount;
		}
	}
	
	delete []rowData;
	delete []colData;
	
	if(bestColCount > 2)
	{
		return destImage.colRange(bestCol,bestCol+bestColCount).clone();
	}
	return destImage;
#else
	if(srcImage.empty())
	{
		return srcImage;
	}
	//去除周围多余的边长
	cv::Mat destImage;
	destImage  = srcImage.clone();
	int bestTopRow = 0;//列的上边界
	int bestRowCount = 0;
	bool isDataFlg = false;
	int Row = 0;
	int rowCount = 0;
	for(int i=0; i<destImage.rows; i++)
	{
		if(cv::countNonZero(destImage.rowRange(i,i+1)))
		{
			if(isDataFlg)
			{
				rowCount ++;
			}
			else
			{
				Row = i;
				rowCount = 1;
				isDataFlg = true;
			}
		}
		else
		{
			isDataFlg = false;
		}
		
		if(rowCount > bestRowCount)
		{
			bestTopRow = Row;
			bestRowCount = rowCount;
		}
	}
	if(bestRowCount > 10)
	{
		destImage = destImage.rowRange(bestTopRow,bestTopRow+bestRowCount).clone();
	}
	int bestCol = 0;//列的上边界
	int bestColCount = 0;
	int Col = 0;
	int colCount = 0;
	isDataFlg = false;
	for(int i=0; i<destImage.cols; i++)
	{
		if(cv::countNonZero(destImage.colRange(i,i+1)))
		{
			if(isDataFlg)
			{
				colCount ++;
			}
			else
			{
				Col = i;
				colCount = 1;
				isDataFlg = true;
			}
		}
		else
		{
			isDataFlg = false;
		}
		
		if(colCount > bestColCount)
		{
			bestCol = Col;
			bestColCount = colCount;
		}
	}
	
	if(bestColCount > 2)
	{
		return destImage.colRange(bestCol,bestCol+bestColCount).clone();
	}
	return destImage;
#endif
}

Mat Vocabulary::getDifferenceImage(const Mat &image1, const Mat &image2)
{
  if(image1.rows != image2.rows || image1.cols != image2.cols)
  {
     return cv::Mat();
  }
  unsigned char *tempArr = new unsigned char[image1.rows * image1.cols];
  memset(tempArr,0,image1.rows * image1.cols);
  for(int row=0; row<image1.rows; row++)
  {
    for(int col=0; col<image1.cols; col++)
    {
      unsigned char value1 = image1.at<unsigned char>(row,col);
      unsigned char value2 = image2.at<unsigned char>(row,col);
      if(value1 && value2)
      {
        tempArr[row*image1.cols + col] = 255;
      }
    }
  }
	cv::Mat result = cv::Mat(image2.rows,image2.cols,image2.type(),tempArr).clone();
	
	delete  tempArr;
  return result;
}
//记录中心垂直方向上  点由黑(背景)到白(有效)的次数，初始点为黑(背景)
int Vocabulary::getLineDescriptor(const Mat &srcImage)
{
  int currentIndexFlg = 0;
  int col = srcImage.cols/2;
  int count = 0;
  for(int i=0; i<srcImage.rows; i++)
  {
    //当前点为黑下一点为白
    if(!currentIndexFlg && (srcImage.at<unsigned char>(i,col) > 0))
    {
      count ++;
    }
    currentIndexFlg = srcImage.at<unsigned char>(i,col)>0?1:0;
  }
  return count;
}

void Vocabulary::getBlockDescriptoy(const Mat &srcImage, int descriptor[])
{
	if(srcImage.rows<0 || srcImage.cols < 0)
	{
		return ;
	}
#if 1
	int rowStep = srcImage.rows / 3;
  int colStep = srcImage.cols / 3;
  descriptor[0] = cv::countNonZero(srcImage.rowRange(rowStep*0,rowStep*1).colRange(colStep*0,colStep*1));
  descriptor[1] = cv::countNonZero(srcImage.rowRange(rowStep*0,rowStep*1).colRange(colStep*1,colStep*2));
  descriptor[2] = cv::countNonZero(srcImage.rowRange(rowStep*0,rowStep*1).colRange(colStep*2,srcImage.cols));

  descriptor[3] = cv::countNonZero(srcImage.rowRange(rowStep*1,rowStep*2).colRange(colStep*0,colStep*1));
  descriptor[4] = cv::countNonZero(srcImage.rowRange(rowStep*1,rowStep*2).colRange(colStep*1,colStep*2));
  descriptor[5] = cv::countNonZero(srcImage.rowRange(rowStep*1,rowStep*2).colRange(colStep*2,srcImage.cols));

  descriptor[6] = cv::countNonZero(srcImage.rowRange(rowStep*2,srcImage.rows).colRange(colStep*0,colStep*1));
  descriptor[7] = cv::countNonZero(srcImage.rowRange(rowStep*2,srcImage.rows).colRange(colStep*1,colStep*2));
  descriptor[8] = cv::countNonZero(srcImage.rowRange(rowStep*2,srcImage.rows).colRange(colStep*2,srcImage.cols));
#else
	int rowStep = srcImage.rows / 4;
	int colStep = srcImage.cols / 2;
	
	descriptor[0] = cv::countNonZero(srcImage.rowRange(rowStep*0,rowStep*1).colRange(colStep*0,colStep*1));
	descriptor[1] = cv::countNonZero(srcImage.rowRange(rowStep*0,rowStep*1).colRange(colStep*1,srcImage.cols));
	
	descriptor[2] = cv::countNonZero(srcImage.rowRange(rowStep*1,rowStep*2).colRange(colStep*0,colStep*1));
	descriptor[3] = cv::countNonZero(srcImage.rowRange(rowStep*1,rowStep*2).colRange(colStep*1,srcImage.cols));
	
	descriptor[4] = cv::countNonZero(srcImage.rowRange(rowStep*2,rowStep*3).colRange(colStep*0,colStep*1));
	descriptor[5] = cv::countNonZero(srcImage.rowRange(rowStep*2,rowStep*3).colRange(colStep*1,srcImage.cols));
	
	descriptor[6] = cv::countNonZero(srcImage.rowRange(rowStep*3,srcImage.rows).colRange(colStep*0,colStep*1));
	descriptor[7] = cv::countNonZero(srcImage.rowRange(rowStep*3,srcImage.rows).colRange(colStep*1,srcImage.cols));
	
	descriptor[8] = 0;
//  descriptor[8] = cv::countNonZero(srcImage.rowRange(rowStep*2,srcImage.rows).colRange(colStep*2,srcImage.cols));
#endif
}

std::vector<int> Vocabulary::charRecognitionDetect(const Mat &srcImage)
{
	long time = clock();
#if 0
	std::multimap<int,Mat> vResultImageVector = this->getTargetArea(srcImage);
	UDEBUG("vResultImageVector size:%d .\n",vResultImageVector.size());
	UDEBUG("Processing images using time:%f S.\n",((float)(clock()-time)/CLOCKS_PER_SEC));
	time = clock();
	std::vector<int> result;
	
	result = this->search(vResultImageVector);
	UDEBUG("find result:%d  using time:%f S.\n",result.size(),((float)(clock()-time)/CLOCKS_PER_SEC));
	return result;
#else
	cv::Mat image_gay;
	if(srcImage.channels() != 1)
	{
		cv::cvtColor(srcImage, image_gay, CV_RGB2GRAY);
	}
	else
	{
		srcImage.convertTo(image_gay,CV_8U);
	}
	image_gay = toBinary(image_gay);
//	UDEBUG("Processing images using time:%f S.\n",((float)(clock()-time)/CLOCKS_PER_SEC));
	
	std::vector< std::vector<int> > resultTemp;
	for(int threshold=100; threshold<121; threshold+=5)
	{
	
//		std::multimap<int,Mat> vResultImageVector = this->getTargetArea(srcImage);
		cv::Mat image_bin;
		cv::threshold(image_gay,image_bin,threshold,255,THRESH_BINARY_INV);
//		UDEBUG("threshold using time:%f S.\n",((float)(clock()-time)/CLOCKS_PER_SEC));
		std::multimap<int,Mat> vResultImageVector = getAllConnectedDomain(image_bin);
//		UDEBUG("getAllConnectedDomain using time:%f S.\n",((float)(clock()-time)/CLOCKS_PER_SEC));
		resultTemp.push_back(search(vResultImageVector));
//		UDEBUG("Search using time:%f S.\n",((float)(clock()-time)/CLOCKS_PER_SEC));
	}
	std::vector<int> result = {0,0,0,0,0,0,0,0};
	for(int i=0; i<result.size(); i++)
	{
		int flgArr[44] = {0};
		for(int index=0; index<resultTemp.size(); index++)
		{
			flgArr[resultTemp[index][i]] ++;
		}
		int maxIndex = 0;
		int secondIndex = 0;
		int max = 0;
		int second = 0;
		for(int t=1; t<44; t++)
		{
			if(0 == flgArr[t])
			{
				continue;
			}
			if(flgArr[t] > max)
			{
				secondIndex = maxIndex;
				second = max;
				
				max = flgArr[t];
				maxIndex = t;
			}
			else if(flgArr[t] > second)
			{
				secondIndex = t;
				second = flgArr[t];
			}
			if(flgArr[t] == max && 31 == t && 2==i)
			{
				max = flgArr[t];
				maxIndex = t;
			}
		}
		
//		UDEBUG("maxIndex:%d max:%d  secondIndex=%d second=%d \n",maxIndex,max,secondIndex,second);
		//0:a  7:h  31:F  2:c  28:C
		if(i == 0 && 28 == maxIndex && 2 == secondIndex)
		{
			if(second > 1)
			{
				result[i] = secondIndex;
			}
		}
		else if(i == 0 && 40 == maxIndex && 9 == secondIndex)
		{
			if(second > 1)
			{
				result[i] = secondIndex;
			}
		}
		else if(26 == maxIndex && 9 == secondIndex )
		{
			if(second > 0)
			{
				result[i] = secondIndex;
			}
		}
		else if((i == 0 || 7 == i) && 1 != maxIndex)
		{
			if(max > 1)
			{
				result[i] = maxIndex;
			}
		}//40:U  36:P  26:A  19:T 12:l
		else if((40 == maxIndex || 36 == maxIndex || 26 == maxIndex || 19 == maxIndex || 34 == maxIndex || 12 == maxIndex))
		{
			if( max > 2)
			{
				result[i] = maxIndex;
			}
		}
		else if(max > 0)
		{
			result[i] = maxIndex;
		}
		
	}
	
	return result;
#endif

}
	
	double Vocabulary::getEntropy(const cv::Mat &srcImage) {
		int hist[256] = {};
		
		for(int row=0; row<srcImage.rows; row++)
		{
			for(int col=0;col<srcImage.cols; col++)
			{
				int index = srcImage.at<uchar>(row,col);
				hist[index] ++;
			}
		}

//    double histPro[256] = {};
		int imageSize = srcImage.rows*srcImage.cols;
		double result = 0.0;
		for(int k=0; k<256; k++)
		{
			
			if(0 == hist[k])
			{
			
			}
			else
			{
				double temp = (double)hist[k]/(double)imageSize;
				result  = result-temp*(log(temp)/log(2.0));
			}
		}
		return  result;
	}
	
	cv::Mat Vocabulary::toBinary(const cv::Mat &srcImage,int threshold) {
		
		cv::Mat Guass_image;
		srcImage.copyTo(Guass_image);
#if 0
		//分成5段进行二值化
//	int offset1 = 80;
//	int offset2 = 220;
//	int offset3 = 430;
//	int offset4 = 560;
	int offset1 = 130;
	int offset2 = 260;
	int offset3 = 390;
	int offset4 = 520;
	
	UDEBUG("Guass_image.rows = %d\n",Guass_image.rows);
	cv::Mat image1 = Guass_image.colRange(0,offset1);
	cv::Mat image2 = Guass_image.colRange(offset1,offset2);
	cv::Mat image3 = Guass_image.colRange(offset2,offset3);
	cv::Mat image4 = Guass_image.colRange(offset3,offset4);
	cv::Mat image5 = Guass_image.colRange(offset4,Guass_image.cols);
	
//	charRecognitionVocabulary->homoFilters(image1,image1,1.2);
//	charRecognitionVocabulary->homoFilters(image2,image2,1.2);
//	charRecognitionVocabulary->homoFilters(image3,image3,1.4);
//	charRecognitionVocabulary->homoFilters(image4,image4,1.2);
//	charRecognitionVocabulary->homoFilters(image5,image5,1.2);
	charRecognitionVocabulary->homoFilters(image1,image1,3);
	charRecognitionVocabulary->homoFilters(image2,image2,3);
	charRecognitionVocabulary->homoFilters(image3,image3,3);
	charRecognitionVocabulary->homoFilters(image4,image4,3);
	charRecognitionVocabulary->homoFilters(image5,image5,3);
	
	cv::GaussianBlur(image1,image1,cv::Size(3, 3), 0, 0);
	cv::GaussianBlur(image2,image2,cv::Size(3, 3), 0, 0);
	cv::GaussianBlur(image3,image3,cv::Size(3, 3), 0, 0);
	cv::GaussianBlur(image4,image4,cv::Size(3, 3), 0, 0);
	cv::GaussianBlur(image5,image5,cv::Size(3, 3), 0, 0);
	
	cv::threshold(image1,image1,252,255,cv::THRESH_OTSU);
	cv::threshold(image2,image2,252,255,cv::THRESH_OTSU);
	cv::threshold(image3,image3,254,255,cv::THRESH_OTSU);
	cv::threshold(image4,image4,252,255,cv::THRESH_OTSU);
	cv::threshold(image5,image5,252,255,cv::THRESH_OTSU);
	
	
//	cv::threshold(image1,image1,252,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image2,image2,252,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image3,image3,254,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image4,image4,252,255,cv::THRESH_BINARY_INV);
//	cv::threshold(image5,image5,252,255,cv::THRESH_BINARY_INV);
	
	for(int row=0;row<Guass_image.rows; row++)
	{
		for(int col=0; col<Guass_image.cols; col++)
		{
			if(col < offset1)
			{
				Guass_image.at<uchar>(row,col) = image1.at<uchar>(row,col);
			}
			else if(col < offset2)
			{
				Guass_image.at<uchar>(row,col) = image2.at<uchar>(row,col-offset1);
			}
			else if(col < offset3)
			{
				Guass_image.at<uchar>(row,col) = image3.at<uchar>(row,col-offset2);
			}
			else if(col < offset4)
			{
				Guass_image.at<uchar>(row,col) = image4.at<uchar>(row,col-offset3);
			}
			else
			{
				Guass_image.at<uchar>(row,col) = image5.at<uchar>(row,col-offset4);
			}
		}
	}
#else
//		int offset1 = 80;
//		int offset2 = 220;
//		int offset3 = 430;
//		int offset4 = 560;
		int offset1 = 128;
		int offset2 = 256;
		int offset3 = 384;
		int offset4 = 512;
		
//		UDEBUG("Guass_image.rows = %d\n",Guass_image.rows);
		cv::Mat image1 = Guass_image.colRange(0,offset1);
		cv::Mat image2 = Guass_image.colRange(offset1,offset2);
		cv::Mat image3 = Guass_image.colRange(offset2,offset3);
		cv::Mat image4 = Guass_image.colRange(offset3,offset4);
		cv::Mat image5 = Guass_image.colRange(offset4,Guass_image.cols);

		homoFilters(image1,image1,1.7);
		homoFilters(image2,image2,1.7);
		homoFilters(image3,image3,1.7);
		homoFilters(image4,image4,1.7);
		homoFilters(image5,image5,1.7);
		
		cv::GaussianBlur(image1,image1,cv::Size(3, 3), 0, 0);
		cv::GaussianBlur(image2,image2,cv::Size(3, 3), 0, 0);
		cv::GaussianBlur(image3,image3,cv::Size(3, 3), 0, 0);
		cv::GaussianBlur(image4,image4,cv::Size(3, 3), 0, 0);
		cv::GaussianBlur(image5,image5,cv::Size(3, 3), 0, 0);
		
//		cv::threshold(image1,image1,threshold,255,cv::THRESH_BINARY);
//		cv::threshold(image2,image2,threshold,255,cv::THRESH_BINARY);
//		cv::threshold(image3,image3,threshold,255,cv::THRESH_BINARY);
//		cv::threshold(image4,image4,threshold,255,cv::THRESH_BINARY);
//		cv::threshold(image5,image5,threshold,255,cv::THRESH_BINARY);
		
		for(int row=0;row<Guass_image.rows; row++)
		{
			for(int col=0; col<Guass_image.cols; col++)
			{
				if(col < offset1)
				{
					Guass_image.at<uchar>(row,col) = image1.at<uchar>(row,col);
				}
				else if(col < offset2)
				{
					Guass_image.at<uchar>(row,col) = image2.at<uchar>(row,col-offset1);
				}
				else if(col < offset3)
				{
					Guass_image.at<uchar>(row,col) = image3.at<uchar>(row,col-offset2);
				}
				else if(col < offset4)
				{
					Guass_image.at<uchar>(row,col) = image4.at<uchar>(row,col-offset3);
				}
				else
				{
					Guass_image.at<uchar>(row,col) = image5.at<uchar>(row,col-offset4);
				}
			}
		}
//		cv::threshold(Guass_image,Guass_image,128,255,cv::THRESH_BINARY_INV);
#endif
		return Guass_image;
	}
	
	int floatToInt(double f)
{
		int i = 0;
		if(f>0) //正数
			i = (f*10 + 5)/10;
		else if(f<0) //负数
			i = (f*10 - 5)/10;
		else i = 0;
		
		return i;
}
} //end  namespace
